package entity

import (
	"errors"
	"fmt"

	"github.com/jinzhu/gorm"
	"gopkg.in/yaml.v2"
)

// Workflow Node节点
type WorkflowNode struct {
	Name           string                 `yaml:"-" json:"name"`
	Type           string                 `yaml:"type" json:"type"`
	Ref            string                 `yaml:"ref" json:"ref"`
	Description    string                 `yaml:"description" json:"description"`
	Targets        []string               `yaml:"targets" json:"targets"`
	Sources        []string               `yaml:"sources" json:"sources"`
	Metadata       map[string]interface{} `yaml:"metadata" json:"metadata"`
	TaskParameters string                 `yaml:"taskparameters" json:"taskParameters"`
}

// Trigger结构
type TriggerDefinition struct {
	Type     string `yaml:"type"`
	Schedule string `yaml:"schedule"`
}

// GlobalParam结构
type ParamDefinition struct {
	Param map[string]string `yaml:"param"`
}

// DSL YAML结构
type WorkflowDefinition struct {
	Name        string                  `yaml:"name"`
	Description string                  `yaml:"description"`
	Workflow    map[string]WorkflowNode `yaml:"workflow"`
	Trigger     TriggerDefinition       `yaml:"trigger"`
	Global      ParamDefinition         `yaml:"global"`
}

// Workflow对象
type Workflow struct {
	RefVersion    string         `gorm:"column:ref_version" json:"-"`
	Ref           string         `gorm:"column:ref" json:"ref"`
	Version       string         `gorm:"column:version" json:"version"`
	Type          string         `gorm:"column:workflow" json:"type"`
	Name          string         `gorm:"column:name" json:"name"`
	Description   string         `gorm:"column:desription" json:"description"`
	WorkflowNodes []WorkflowNode `gorm:"-" json:"nodes"`
	DSLText       string         `gorm:"column:dsl_text" json:"dslText"`
}

func (*Workflow) TableName() string {
	return "workflow"
}

func (w *Workflow) AfterFind(tx *gorm.DB) (err error) {
	err = w.UnmarshalDSL()
	return err
}

// 从 Workflow.DSLText 解析为 WorkflowNodes
func (w *Workflow) UnmarshalDSL() (err error) {
	definition := new(WorkflowDefinition)
	err = yaml.Unmarshal([]byte(w.DSLText), definition)
	fmt.Println(definition.Name)
	fmt.Println(definition.Description)
	for key, node := range definition.Workflow {
		node.Ref = key
		node.Name = key
		w.WorkflowNodes = append(w.WorkflowNodes, node)
	}
	return err
}

// 检查DSL是否符合规范
func (w *Workflow) Check() (err error) {
	/*
	var nextNodes []WorkflowNode
	preNode, err := w.FirstNode()
	if err != nil {
		return err
	}
	for {
		nextNodes, err := w.NextNodes(preNode)
		if err != nil {
			return err
		}

	}*/
	return nil
}

// 查找start节点
func (w *Workflow) FirstNode() (node *WorkflowNode, err error) {
	indexs := make([]int, 0)
	for _index, _node := range w.WorkflowNodes {
		if _node.Type == "start" {
			indexs = append(indexs, _index)
		}
	}
	if len(indexs) == 1 {
		return &w.WorkflowNodes[indexs[0]], nil
	} else if len(indexs) > 1 {
		return nil, errors.New("More than one start node")
	} else {
		return nil, errors.New("No start node found")
	}
}

// 查找下一步的节点
func (w *Workflow) NextNodes(node *WorkflowNode) (nodes []WorkflowNode, err error) {
	return nil, nil
}
